
package com.jf.cloud.multishop.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.constant.IsPassShopEnum;
import com.jf.cloud.common.constant.StatusEnum;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.multishop.constant.IsDefault;
import com.jf.cloud.multishop.constant.ShopWithdrawCashStatus;
import com.jf.cloud.multishop.dto.ShopBankCardDTO;
import com.jf.cloud.multishop.mapper.ShopAuditingMapper;
import com.jf.cloud.multishop.mapper.ShopBankCardMapper;
import com.jf.cloud.multishop.mapper.ShopWithdrawCashMapper;
import com.jf.cloud.multishop.model.ShopBankCard;
import com.jf.cloud.multishop.service.ShopApplyService;
import com.jf.cloud.multishop.service.ShopBankCardService;
import com.jf.cloud.multishop.vo.ShopBankCardVO;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author zz
 * @Date 2021/4/25 17:02
 */
@Service
public class ShopBankCardServiceImpl implements ShopBankCardService {

    @Autowired
    private ShopBankCardMapper shopBankCardMapper;

    @Autowired
    private ShopWithdrawCashMapper shopWithdrawCashMapper;

    @Autowired
    private ShopAuditingMapper shopAuditingMapper;

    @Autowired
    private ShopApplyService shopApplyService;

    @Autowired
    private MapperFacade mapperFacade;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBatch(List<ShopBankCardDTO> shopBankCardDTOList, Long shopId) {
        if (CollUtil.isEmpty(shopBankCardDTOList)) {
            return;
        }
        List<ShopBankCardVO> shopBankCardVos = shopBankCardMapper.listByShopId(shopId);
        if (CollUtil.isEmpty(shopBankCardVos)) {
            shopBankCardVos = new ArrayList<>();
        }
        // 检查银行卡信息
        this.checkSaveBankCardList(shopBankCardVos, shopBankCardDTOList, shopId);
        shopBankCardMapper.insertBatch(shopBankCardDTOList, shopId);
    }

    @Override
    public List<ShopBankCardVO> listByShopId(Long shopId) {
        return shopBankCardMapper.listByShopId(shopId);
    }

    @Override
    public void deleteByShopBankCardId(Long shopBankCardId, Long shopId) {
        ShopBankCardVO shopBankCard = shopBankCardMapper.getByShopBankCardId(shopBankCardId);
        if (Objects.equals(shopBankCard.getIsDefault(), 1)) {
            // 不能删除默认银行卡
            throw new LuckException("不能删除默认银行卡");
        }
        // 检查是否为最后一张银行卡
        if (shopBankCardMapper.countByShopId(shopId) == 1) {
            throw new LuckException("至少保留一张银行卡");
        }
        // 检查是否属于当前店铺
        this.checkIsCurrentShop(shopId, shopBankCardId);
        // 检查是否处于提现状态
        this.checkIsWithdraw(shopBankCardId);
        // 进行删除
        shopBankCardMapper.deleteById(shopBankCardId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBatchAndSubmitApply(List<ShopBankCardDTO> shopBankCardDTOList, Long shopId) {
        if (Objects.equals(AuthUserContext.get().getIsPassShop(), IsPassShopEnum.YES.value())) {
            // 店铺已入驻不能调用该方法
            throw new LuckException("接口调用错误");
        }
        if (shopBankCardDTOList == null || shopBankCardDTOList.size() == 0) {
            throw new LuckException("至少要添加一个银行卡");
        }
        // 先删除已保存的银行卡信息
        shopBankCardMapper.deleteByShopId(AuthUserContext.get().getTenantId());
        // 检查银行卡信息
        this.checkSaveBankCardList(new ArrayList<>(), shopBankCardDTOList, shopId);
        // 保存银行卡信息
        shopBankCardMapper.insertBatch(shopBankCardDTOList, shopId);
        // 提交开店申请
        shopApplyService.apply(shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateByShopId(ShopBankCardDTO shopBankCardDTO, Long shopId) {
        if (Objects.isNull(shopBankCardDTO.getShopBankCardId())) {
            throw new LuckException("银行卡信息错误");
        }
        List<ShopBankCardVO> shopBankCardVOList = this.listByShopId(shopId);
        // 检查银行卡是否属于当前店铺
        this.checkIsCurrentShop(shopId, shopBankCardDTO.getShopBankCardId());
        // 检查是否处于提现状态
        this.checkIsWithdraw(shopBankCardDTO.getShopBankCardId());
        // 检查银行卡信息
        this.checkSaveBankCardList(shopBankCardVOList, Collections.singletonList(shopBankCardDTO), shopId);
        shopBankCardMapper.update(mapperFacade.map(shopBankCardDTO, ShopBankCard.class));
        if (Objects.equals(shopBankCardDTO.getIsDefault(), IsDefault.YES.value())) {
            shopBankCardMapper.setPrimary(shopBankCardDTO.getShopBankCardId(), shopId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setPrimaryByShopId(Long shopBankCardId, Long shopId) {
        this.checkIsCurrentShop(shopId, shopBankCardId);
        shopBankCardMapper.setPrimary(shopBankCardId, shopId);
    }

    @Override
    public void setNotPrimaryByShopId(Long shopBankCardId, Long shopId) {
        this.checkIsCurrentShop(shopId, shopBankCardId);
        shopBankCardMapper.setNotPrimary(shopBankCardId,shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertByShopId(ShopBankCardDTO shopBankCardDTO, Long shopId) {
        if (Objects.isNull(shopBankCardDTO)) {
            return;
        }
        List<ShopBankCardVO> shopBankCardVOList = this.listByShopId(shopId);
        if (CollUtil.isEmpty(shopBankCardVOList)) {
            shopBankCardVOList = new ArrayList<>();
        }
        // 检查银行卡信息
        this.checkSaveBankCardList(shopBankCardVOList, Collections.singletonList(shopBankCardDTO), shopId);
        ShopBankCard shopBankCard = mapperFacade.map(shopBankCardDTO, ShopBankCard.class);
        shopBankCard.setShopId(shopId);
        shopBankCard.setStatus(StatusEnum.ENABLE.value());
        shopBankCardMapper.save(shopBankCard);
        if (Objects.equals(shopBankCardDTO.getIsDefault(), 1)) {
            shopBankCardMapper.setPrimary(shopBankCard.getShopBankCardId(), shopId);
        }
    }

    @Override
    public ShopBankCardVO getByShopBankCardId(Long shopBankCardId) {
        return shopBankCardMapper.getByShopBankCardId(shopBankCardId);
    }

    @Override
    public ShopBankCardVO getByShopBankCardIdAndShopId(Long shopBankCardId, Long shopId) {
        ShopBankCardVO shopBankCardVO = shopBankCardMapper.getByShopBankCardId(shopBankCardId);
        if (!Objects.equals(shopBankCardVO.getShopId(), shopId)) {
            throw new LuckException("当前银行卡不属于该店铺");
        }
        return shopBankCardVO;
    }

    /**
     * 检查银行卡列表信息
     * @param savedBankCardList 已保存的银行卡列表
     * @param newBankCardList 新增的银行卡列表
     * @param shopId 用于保存银行卡的店铺id
     */
    private void checkSaveBankCardList(List<ShopBankCardVO> savedBankCardList, List<ShopBankCardDTO> newBankCardList, Long shopId) {
        if (savedBankCardList.size() + newBankCardList.size() > Constant.SHOP_BANK_CARD_LIMIT_NUM) {
            throw new LuckException("银行卡数量不能超过" + Constant.SHOP_BANK_CARD_LIMIT_NUM);
        }
        Map<String, Integer> bankCardMap = new HashMap<>(5);
        savedBankCardList.forEach(item -> {
            if (bankCardMap.containsKey(item.getCardNo())) {
                throw new LuckException("已添加的银行卡中存在重复账号" + item.getCardNo() + "，请先删除重复的银行卡账号");
            }
            bankCardMap.put(item.getCardNo(), 1);
        });
        newBankCardList.forEach(item -> {
            //新增的需要校验
            if (Objects.isNull(item.getShopBankCardId()) && bankCardMap.containsKey(item.getCardNo())) {
                throw new LuckException("银行卡账号" + item.getCardNo() + "重复");
            }
            bankCardMap.put(item.getCardNo(), 1);
        });
    }

    /**
     * 检查是否处于提现状态
     * @param shopBankCardId 银行卡id
     */
    private void checkIsWithdraw(Long shopBankCardId) {
        int count = shopWithdrawCashMapper.countByShopBandCardIdAndStatus(shopBankCardId, ShopWithdrawCashStatus.WAITAUDIT.value());
        if (count > 0) {
            // 正在用于提现的银行卡不能删除
            throw new LuckException("正在用于提现的银行卡账号不能修改或删除");
        }
    }

    /**
     * 检查银行卡是否属于当前店铺
     * @param shopId
     * @param shopBankCardId
     */
    private void checkIsCurrentShop(Long shopId, Long shopBankCardId) {
        if (Objects.equals(shopId, Constant.PLATFORM_SHOP_ID)) {
            // 平台端操作
            return;
        }
        ShopBankCardVO shopBankCard = this.shopBankCardMapper.getByShopBankCardId(shopBankCardId);
        if (!Objects.equals(shopBankCard.getShopId(), shopId)) {
            throw new LuckException("当前银行卡不属于你的店铺");
        }
    }
}
